/*
 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TLS_WIRELESS_H
#define TLS_WIRELESS_H

#include "tls_common.h"
#include "wm_osal.h"
#include "list.h"

struct tls_wif;
struct wpa_supplicant;

/* Maximum size of the SSID  */
#define IW_SSID_MAX_SIZE    32

enum ieee80211_wireless_mode {
    IEEE80211_MODE_11B = 0,
    IEEE80211_MODE_11G,
    IEEE80211_MODE_11NG_HT20,
    IEEE80211_MODE_11NG_HT40PLUS,
    IEEE80211_MODE_11NG_HT40MINUS,
    IEEE80211_MODE_MAX,
};

#define IW_AUTH_INDEX        0x0FFF
#define IW_AUTH_FLAGS        0xF000

#define IW_AUTH_WPA_VERSION        0
#define IW_AUTH_CIPHER_PAIRWISE        1
#define IW_AUTH_CIPHER_GROUP        2
#define IW_AUTH_KEY_MGMT        3
#define IW_AUTH_TKIP_COUNTERMEASURES    4
#define IW_AUTH_DROP_UNENCRYPTED    5
#define IW_AUTH_80211_AUTH_ALG        6
#define IW_AUTH_WPA_ENABLED        7
#define IW_AUTH_RX_UNENCRYPTED_EAPOL    8
#define IW_AUTH_ROAMING_CONTROL        9
#define IW_AUTH_PRIVACY_INVOKED        10
#define IW_AUTH_CIPHER_GROUP_MGMT    11
#define IW_AUTH_MFP            12

/* IW_AUTH_WPA_VERSION values (bit field) */
#define IW_AUTH_WPA_VERSION_DISABLED    0x00000001
#define IW_AUTH_WPA_VERSION_WPA        0x00000002
#define IW_AUTH_WPA_VERSION_WPA2    0x00000004

/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT
 * values (bit field) */
#define IW_AUTH_CIPHER_NONE    0x00000001
#define IW_AUTH_CIPHER_WEP40    0x00000002
#define IW_AUTH_CIPHER_TKIP    0x00000004
#define IW_AUTH_CIPHER_CCMP    0x00000008
#define IW_AUTH_CIPHER_WEP104    0x00000010
#define IW_AUTH_CIPHER_AES_CMAC    0x00000020

/* IW_AUTH_KEY_MGMT values (bit field) */
#define IW_AUTH_KEY_MGMT_802_1X    1
#define IW_AUTH_KEY_MGMT_PSK    2

/* IW_AUTH_80211_AUTH_ALG values (bit field) */
#define IW_AUTH_ALG_OPEN_SYSTEM    0x00000001
#define IW_AUTH_ALG_SHARED_KEY    0x00000002
#define IW_AUTH_ALG_LEAP    0x00000004

#define IW_ENCODE_ALG_NONE    0
#define IW_ENCODE_ALG_WEP    1
#define IW_ENCODE_ALG_TKIP    2
#define IW_ENCODE_ALG_CCMP    3
#define IW_ENCODE_ALG_PMK    4
#define IW_ENCODE_ALG_AES_CMAC    5

#define IW_MAX_FREQUENCIES    32

#define IW_SCAN_TYPE_ACTIVE   0
#define IW_SCAN_TYPE_PASSIVE  1

struct    iw_scan_req {
    u8        scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
    u8 ssid_len;
    u8        num_channels; /* num entries in channel_list;
                           * 0 = scan all allowed channels */
    u8        bssid[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
                              * individual address of a specific BSS */

    u8        ssid[IW_SSID_MAX_SIZE];
    u32     extra_ies_len;
    u8      extra_ies[0];
};

/**
 * struct beacon_parameters - beacon parameters
 *
 * Used to configure the beacon for an interface.
 *
 * @head: head portion of beacon (before TIM IE)
 *     or %NULL if not changed
 * @tail: tail portion of beacon (after TIM IE)
 *     or %NULL if not changed
 * @interval: beacon interval or zero if not changed
 * @dtim_period: DTIM period or zero if not changed
 * @head_len: length of @head
 * @tail_len: length of @tail
 */
struct iw_beacon_parameters {
    u8 *head, *tail;
    int interval, dtim_period;
    int head_len, tail_len;
};

struct iw_ssid_params {
    u8      ssid[IW_SSID_MAX_SIZE];
    u8      ssid_len;
    u32     ie_len;
    u8      *ie;
};

struct iw_key_params {
    u8          key[32];
    u8          tsc[32];
    u32         key_len;
    u32         tsc_len;
    u16         cipher;
    bool        pairwise;
    bool        default_key;
    u32         key_idx;
    u8          addr[ETH_ALEN];
};

struct iw_sta_add_params {
    const u8 *addr;
    u16 aid;
    u16 capability;
    u16 listen_interval;
    u8  mode;
    const u8 *supp_rates;
    u32 supp_rates_len;
    u32 flags; /* bitmask of WPA_STA_* flags */
};

/**
 * struct beacon_parameters - beacon parameters
 *
 * Used to configure the beacon for an interface.
 *
 * @head: head portion of beacon (before TIM IE)
 *     or %NULL if not changed
 * @tail: tail portion of beacon (after TIM IE)
 *     or %NULL if not changed
 * @interval: beacon interval or zero if not changed
 * @dtim_period: DTIM period or zero if not changed
 * @head_len: length of @head
 * @tail_len: length of @tail
 */
struct beacon_parameters {
    u8 *head, *tail;
    int interval, dtim_period;
    int head_len, tail_len;
};

struct wl_event_reload {
    bool reload;
};

struct wl_event_join_ibss_info {
    u8  bssid[ETH_ALEN];
    u32 freq;
};

struct wl_event_mic_err {
    u8 bssid[ETH_ALEN];
    u8 addr[ETH_ALEN];
    bool group_mic_err;       /* TRUE: group, FALSE: pairwise */
};

struct wl_event_rx_eapol {
    u8 *src_addr;
    u8 *eapol_body;
    u32 eapol_body_len;
#if TLS_CONFIG_AP
    u8 mode;
#endif
};

struct wl_event_rx_mgmt {
    u8 *mgmt;
    u32 mgmt_len;
};

struct wl_event_rx_from_unknown {
    u8 addr[ETH_ALEN];
};

struct wl_event_assoc_info {
    /**
     * reassoc - Flag to indicate association or reassociation
     */
    int reassoc;

    /**
     * req_ies - (Re)Association Request IEs
     *
     * If the driver generates WPA/RSN IE, this event data must be
     * returned for WPA handshake to have needed information. If
     * wpa_supplicant-generated WPA/RSN IE is used, this
     * information event is optional.
     *
     * This should start with the first IE (fixed fields before IEs
     * are not included).
     */
    const u8 *req_ies;

    /**
     * req_ies_len - Length of req_ies in bytes
     */
    u32 req_ies_len;

    /**
     * resp_ies - (Re)Association Response IEs
     *
     * Optional association data from the driver. This data is not
     * required WPA, but may be useful for some protocols and as
     * such, should be reported if this is available to the driver
     * interface.
     *
     * This should start with the first IE (fixed fields before IEs
     * are not included).
     */
    u8 *resp_ies;

    /**
     * resp_ies_len - Length of resp_ies in bytes
     */
    u32 resp_ies_len;

    /**
     * addr - Station address (for AP mode)
     */
    u8 *addr;

    u8 *bssid;

    /**
     * freq - Frequency of the operational channel in MHz
     */
    unsigned int freq;
};

struct tls_wl_event_ops {
    int (*ibss_joined)(struct tls_wif *wif,
            struct wl_event_join_ibss_info *info);
    int (*assoc)(struct tls_wif *wif,
            struct wl_event_assoc_info *info);
    int (*disassoc)(struct tls_wif *wif);
    int (*scan_completed)(struct tls_wif *wif);
    int (*mic_err)(struct tls_wif *wif,
            struct wl_event_mic_err *info);
    int (*rx_eapol)(struct tls_wif *wif,
            struct wl_event_rx_eapol *eapol);
    int (*rx_mgmt)(struct tls_wif *wif,
            struct wl_event_rx_mgmt *mgmt);
    int (*mac_wdg)(struct tls_wif *wif);
    int (*chip_wakeup)(struct tls_wif *wif);
#if TLS_CONFIG_AP_OPT_PS
    int (*beacon_done)(struct tls_wif *wif);
    int (*rx_ps)(struct tls_wif *wif,
            struct wl_event_rx_mgmt *mgmt);
    int (*rx_pspoll)(struct tls_wif *wif,
            struct wl_event_rx_from_unknown *rx_pspoll);
    int (*sta_active)(struct tls_wif *wif,
            struct wl_event_rx_from_unknown *rx_pspoll);
#endif
    int (*rx_from_unknown_sta)(struct tls_wif *wif,
            struct wl_event_rx_from_unknown *rx_from_unknown);
    int (*net_down)(struct tls_wif *wif);
    int (*net_fail)(struct tls_wif *wif);
    int (*net_up)(struct tls_wif *wif);
    int (*update_stat)(struct tls_wif *wif, void *cur_bss); /* struct ieee80211_bss *cur_bss */
};

/* sk_buff allocated by wlan driver  */
struct sk_buff {
    struct dl_list list;
    u8   *buf;
    u32   buf_len;
    u32   flags;
};

struct tls_wif {
    struct ieee80211_if_data *priv;
    struct wpa_supplicant *wpa_s;
    struct tls_wl_event_ops *ops;
#if TLS_CONFIG_SOFTAP_11N
    struct hostapd_iface *apif;
#endif

    bool   wlan_create;
    int (*rx_data_cb)(const u8 *bssid, u8 *buf, u32 buf_len);
#if TLS_CONFIG_AP
    bool   wmm_set;
    void  *client_event_callback;
#if TLS_CONFIG_AP_OPT_FWD
    int (*rx_ip_cb)(const u8 *bssid, u8 *buf, u32 buf_len);
#endif
#endif
};

void tls_wl_print_stats(struct tls_wif *wif);

int tls_wl_if_scan(struct tls_wif *wif,
    struct iw_scan_req *scan_req, u16 size);
int tls_wl_if_scan_result2(struct tls_wif *wif,
    u8 *ssid, u32 ssid_len, u8 *buf, u32 buf_size);
int tls_wl_if_scan_result(struct tls_wif *wif,  u8 *buf, u32 buf_size);
void tls_wl_if_sta_flush(struct tls_wif *wif, u8 mode);
int tls_wl_if_sta_deauth(struct tls_wif *wif, u8 *own_addr,
    const u8 *addr, int reason);
int tls_wl_if_sta_disassoc(struct tls_wif *wif, u8 *own_addr,
    const u8 *addr, int reason);
#if TLS_CONFIG_AP
int tls_wl_if_set_tx_queue_params(struct tls_wif *wif, int queue,
    int aifs, int cw_min, int cw_max, int burst_time);
void tls_wl_if_set_sta_flags(struct tls_wif *wif, u8 *addr, u32 flags);
int tls_wl_if_send_channel_switch(struct tls_wif *wif, u8 *ownaddr, u8 newch);
void tls_wl_if_switch_channel_width(struct tls_wif *wif, u8 *ownaddr);
void tls_wl_if_channel_info_updata(struct tls_wif *wif);
#if TLS_CONFIG_SOFTAP_11N
void tls_wl_if_get_ht_param(struct tls_wif *wif, u16 *cap, u8 *mcs, u8 *mpdu);
void tls_wl_if_set_sta_ht_param(struct tls_wif *wif, u8 *mac, u8 *ht);
#endif
#endif
int tls_wl_if_set_mode(struct tls_wif *wif, u16 mode);
int tls_wl_if_clear_mode(struct tls_wif *wif, u16 mode);
int tls_wl_if_set_bssid(struct tls_wif *wif, const u8 *addr, u32 mode);
int tls_wl_if_set_ssid(struct tls_wif *wif, struct iw_ssid_params *params);
int tls_wl_if_set_auth(struct tls_wif *wif, u16 flag, u32 value, u8 mode);
int tls_wl_if_set_ps_mode(struct tls_wif *wif, int powersave);
int tls_wl_if_set_freq(struct tls_wif *wif,
    int freq);
int tls_wl_if_send_eapol(struct tls_wif *wif,
    u8 *buf, u32 len, bool is_apsta);
int tls_wl_if_xmit(struct tls_wif *wif, void *buf, int len, bool is_apsta, bool not_delay);
int tls_wl_if_add_key(struct tls_wif *wif,
    struct iw_key_params *params);
int tls_wl_if_remove_key(struct tls_wif *wif,
                         u32 cipher,
                         u32 key_idx,
                         bool pairwise,
                         u8 *addr);
int tls_wl_if_send_mlme(struct tls_wif *wif,
    u8 *buf, u32 len);
int tls_wl_if_set_rate_mode(struct tls_wif *wif,
    u32 rate_mode);
int tls_wl_if_set_beacon(struct tls_wif *wif,
    struct iw_beacon_parameters *params);
int tls_wl_if_del_beacon(struct tls_wif *wif);
int tls_wl_if_sta_add(struct tls_wif *wif,
    struct iw_sta_add_params *params);
int tls_wl_if_sta_remove(struct tls_wif *wif, u8 *addr);
int tls_wl_if_get_inact_sec(struct tls_wif *wif, const u8 *addr);
int tls_wl_if_get_scan_res(struct tls_wif *wif, u8 *buf, u32 buf_size);
int tls_wl_if_disconnect(struct tls_wif *wif);
int tls_wl_if_tx(struct tls_wif *wif,
    u8 *buf, u32 buflen, bool last_packet, bool is_apsta, bool not_delay);
int tls_wl_if_set_max_rate(struct tls_wif *wif, u8 max_rate_idx);
int tls_wl_if_get_max_rate(struct tls_wif *wif, u8 *max_rate_idx);
#if TLS_CONFIG_IBSS
int tls_wl_if_set_adhoc(struct tls_wif *wif, int adhoc_automode);
#endif
int tls_wl_if_ps(int wake_up);
void tls_wl_if_set_errno(int eno);
int  tls_wl_if_get_errno(void);
void  tls_wl_if_perror(const char *info);
const char *tls_wl_if_get_errinfo(int eno);
#endif /* end of TLS_WIRELESS_H */
